<template>
  <div :id="socketURI"
    :ref="socketURI"
    class="xterm"
    v-loading="loading"
    :element-loading-text="loadingText"
    element-loading-spinner="el-icon-loading"
    element-loading-background="rgba(0, 0, 0, 0.6)"
  ></div>
</template>

<script>
import 'xterm/css/xterm.css'
import { Terminal} from 'xterm'
import { FitAddon } from 'xterm-addon-fit'
//import { WebLinksAddon } from 'xterm-addon-web-links';
import { debounce } from '@/utils/util.js'

import * as sysApis from '@/api/sys'

  export default {
    name: 'XtermShell',
    props: {
      id: null,
      socketURI: {
        type: String,
        default: ''
      },
    },
    data() {
      return {
        term: null,
        fitAddon: null,
        socket: '',
        count: 0,
        accessToken: 'token',
        loading: true,
        first: true,
        loadingText: '初始化……',
        theme:null,
      }
    },
    mounted() {
      this.getTheme().then(res=>{
        if(res.data!=null){
            this.theme={}
            this.theme.background=res.data.background
            this.theme.foreground=res.data.foreground
          }
        this.initSocket()
        this.onTerminalResize()
      })
      
    },
    beforeDestroy() {
      this.socket && this.socket.close();
      this.term && this.term.dispose();
      window.removeEventListener('resize', this.onResize);
    },
    methods: {
       initTerm() {
        
        if(this.theme!=null){
          this.term = new Terminal({
            theme:this.theme,
            cursorBlink:true
          });
        }else{
          this.term = new Terminal({
            cursorBlink:true,
            //cursorStyle: 'underline', //光标样式
          });
        }
        let connectTabElement = this.$refs[this.socketURI]
        this.term.open(connectTabElement);

        this.fitAddon = new FitAddon();// 全屏插件
        this.term.loadAddon(this.fitAddon);
        this.fitAddon.fit();
        this.textCopy()
        
        this.term.focus();
        this.termOnData()
        

      },
      //复制内容到终端
      textCopy(){
        // 监听右键单击事件
        this.term.element.addEventListener('contextmenu', async(event) => {
          // 阻止默认的上下文菜单
          event.preventDefault();
          let temData='';
          const selectedText = window.getSelection().toString();
          if(!selectedText||selectedText==''){
            temData= await navigator.clipboard.readText(); // 获取剪贴板中的文本内容
          }else{
            temData=selectedText
          }
          if(temData&&temData!=''){
            this.socket.send(
                    JSON.stringify({
                        data: JSON.stringify({ ctlMsg: temData }),
                        type: 'ShellCtlMsg'
                    })
                  );
            this.term.focus();
          }
          
        });
      },
      initSocket() {
        // 2.webSocket初始化
        if (this.socketURI === '') return;
        this.socket = new WebSocket(this.socketURI);
        this.socketOnOpen()
        this.socketOnMessage()
        this.socketOnClose()
        this.socketOnError()
        this.initTerm()
        // setTimeout(() => {
        //   this.fitAddon.fit();
        // }, 100)
      },
      onResize: debounce(function () {
        // const terminalContainer = this.$refs[this.socketURI]
        // const fontSize = parseInt(window.getComputedStyle(terminalContainer).getPropertyValue('font-size'), 10);
        // const bounds = terminalContainer.getBoundingClientRect();
        // const cols = Math.floor(bounds.width / fontSize);
        // const rows = Math.floor(bounds.height / fontSize);
        // this.term.resize(cols, rows);

        this.fitAddon.fit()
        // this.term.resize(this.term.cols, this.term.rows) // 重新适应宽高后，重新设置term的cols和rows
        this.term.scrollToBottom() // 滚动到term的最后一行
      }, 500),
      // 监听输入发送数据
      termOnData() {
        this.term.onData((key) => {
          this.socket.send(
            JSON.stringify({
                data: JSON.stringify({ ctlMsg: key }),
                type: 'ShellCtlMsg'
            })
          );
        });
      },
      socketOnMessage () {
        this.socket.onmessage = (e) => {
          const data = JSON.parse(e.data);
          switch(data.type){
            case 'Status':
              const sshStatus = JSON.parse(data.data).sshStatus
              const msg = JSON.parse(data.data).msg
              this.loadingText = msg
              if(sshStatus === 'CONNECTED'){
                // 成功
                this.loading = false
              }else if(sshStatus === 'INIT'){
                // 初始化
                this.loadingText = '初始化……'
              }else if (sshStatus === 'CONNECTING') {
                // 连接中
                this.loadingText = `连接中……`
              }else if(sshStatus === 'ERROR') {
                this.loading = true
                this.loadingText = msg
              }else if(sshStatus === 'FINISH'){
                // 失败
                this.$confirm(`连接失败，是否重连?`, '提示', {
                  confirmButtonText: '继续',
                  cancelButtonText: '取消',
                  type: 'warning'
                }).then(() => {
                  this.initSocket();
                }).catch(() => {
                  this.$message({
                    type: 'info',
                    message: '已取消重连'
                  });
                });
              }else {
                // 结束
                this.socketOnClose()
              }
              break
            case 'ShellTerminalMsg':
              // 第一次连接成功将 initText 清空
              // if (this.first) {
              //   this.first = false
              //   this.term.reset()
              //   this.term.element && this.term.focus()
              //   // this.resizeRemoteTerminal()
              // }
              this.term.write(JSON.parse(data.data).msg);
              break
            default:
            break
          }
        }
      },
      socketOnOpen() {
        this.socket.onopen = () => {
          this.socket.send(JSON.stringify({
              data:JSON.stringify({dataId: this.id}),
              type: 'ShellConn'
          }))
        }
      },
      socketOnClose() {
        // this.socket.onclose = () => {
        //   this.term.write('Bye Bye! \r\n$');
        // }
      },
      socketOnError() {
        // this.$confirm(`连接失败，是否继续?`, '提示', {
        //   confirmButtonText: '确定',
        //   cancelButtonText: '取消',
        //   type: 'warning'
        // }).then(() => {
        //   this.initSocket();
        // }).catch(() => {
        //   this.$message({
        //     type: 'info',
        //     message: '已取消重连'
        //   });
        // });
        // const maxCount = 3;
        // this.socket.onerror = () => {
        // if (this.count < maxCount) {
        //   this.count++;
        //   console.log(`第 ${this.count} 次重连`);
        //   setTimeout(() => {
        //     this.initSocket();
        //   }, 2000);
        // } else {
        //   console.log('重连失败');
        //   this.$confirm(`${this.count} 次重连失败，是否继续?`, '提示', {
        //     confirmButtonText: '确定',
        //     cancelButtonText: '取消',
        //     type: 'warning'
        //   }).then(() => {
        //     this.initSocket();
        //   }).catch(() => {
        //     this.$message({
        //       type: 'info',
        //       message: '已取消重连'
        //     });
        //   });
        // }
        // };
      },
      onTerminalResize () {
        window.addEventListener('resize', this.onResize)
        this.term.onResize(this.resizeRemoteTerminal)
      },
      resizeRemoteTerminal() {
        // const { cols, rows } = this.term
        // console.warn('cols, rows', cols, rows)
        // 调整后端终端大小 使后端与前端终端大小一致
        // this.isWsOpen && this.ws.send(packResize(cols, rows))
      },
       //获取主题
     async getTheme(){
       return await sysApis.getTheme({})
      },
    }
  }
</script>

<style lang="scss" scoped>
.xterm{
  width:100%;
  height: 100%;
  white-space: nowrap;
  /deep/.xterm-rows{
    white-space: nowrap;
  }
}
</style>
